{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Simple classification example with missing feature handling and parameter tuning\n",
    "\n",
    "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/catboost/tutorials/blob/master/classification/classification_with_parameter_tuning_tutorial.ipynb)\n",
    "\n",
    "This tutorial will show you how to use CatBoost to train binary classifier for data with missing feature and how to do hyper-parameter tuning using Hyperopt framework.\n",
    "\n",
    "Gaps in data may be a challenge to handle correctly, especially when they appear in categorical features, this tutorial will also give some advices how to handle them during model application."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install -q numpy pandas catboost hyperopt scikit-learn matplotlib "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.15.1\n"
     ]
    }
   ],
   "source": [
    "import catboost\n",
    "print(catboost.__version__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from __future__ import absolute_import, division, print_function, unicode_literals"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CatBoost version 0.15.1\n",
      "NumPy version 1.16.4\n",
      "Pandas version 0.24.2\n",
      "Hyperopt version 0.2\n"
     ]
    }
   ],
   "source": [
    "import catboost as cb\n",
    "import catboost.datasets as cbd\n",
    "import catboost.utils as cbu\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import hyperopt\n",
    "import sys\n",
    "\n",
    "# print module versions for reproducibility\n",
    "print('CatBoost version {}'.format(cb.__version__))\n",
    "print('NumPy version {}'.format(np.__version__))\n",
    "print('Pandas version {}'.format(pd.__version__))\n",
    "print('Hyperopt version {}'.format(hyperopt.__version__))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "    Download \"Adult Data Set\" [1] from UCI Machine Learning Repository.\n",
      "\n",
      "    Will return two pandas.DataFrame-s, first with train part (adult.data) and second with test part\n",
      "    (adult.test) of the dataset.\n",
      "\n",
      "    [1]: https://archive.ics.uci.edu/ml/datasets/Adult\n",
      "    \n"
     ]
    }
   ],
   "source": [
    "# We are going to use UCI Adult Data Set because it has both numerical and categorical \n",
    "# features and also has missing features.\n",
    "print(cbd.adult.__doc__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_fixed_adult():\n",
    "    train, test = cbd.adult()\n",
    "    \n",
    "    # CatBoost doesn't support pandas.DataFrame missing values for categorical features out \n",
    "    # of the box (seed issue #571 on GitHub or issue MLTOOLS-2785 in internal tracker). So \n",
    "    # we have to replace them with some designated string manually. \n",
    "    for dataset in (train, test, ):\n",
    "        for name in (name for name, dtype in dict(dataset.dtypes).items() if dtype == np.object):\n",
    "            dataset[name].fillna('nan', inplace=True)\n",
    "            \n",
    "    # CatBoost doesn't support `class_names` in `Pool` c-tor (see MLTOOLS-2799 in internal \n",
    "    # tracker) so we have to convert them manually\n",
    "    class_names = ('<=50K', '>50K', )\n",
    "    for dataset in (train, test, ):\n",
    "        dataset.income = dataset.income.map({'<=50K': 0., '>50K': 1.})\n",
    "    \n",
    "    X_train, y_train = train.drop('income', axis=1), train.income\n",
    "    X_test, y_test = test.drop('income', axis=1), test.income\n",
    "    return X_train, y_train, X_test, y_test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train, y_train, X_test, y_test = get_fixed_adult()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>age</th>\n",
       "      <th>workclass</th>\n",
       "      <th>fnlwgt</th>\n",
       "      <th>education</th>\n",
       "      <th>education-num</th>\n",
       "      <th>marital-status</th>\n",
       "      <th>occupation</th>\n",
       "      <th>relationship</th>\n",
       "      <th>race</th>\n",
       "      <th>sex</th>\n",
       "      <th>capital-gain</th>\n",
       "      <th>capital-loss</th>\n",
       "      <th>hours-per-week</th>\n",
       "      <th>native-country</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>39.0</td>\n",
       "      <td>State-gov</td>\n",
       "      <td>77516.0</td>\n",
       "      <td>Bachelors</td>\n",
       "      <td>13.0</td>\n",
       "      <td>Never-married</td>\n",
       "      <td>Adm-clerical</td>\n",
       "      <td>Not-in-family</td>\n",
       "      <td>White</td>\n",
       "      <td>Male</td>\n",
       "      <td>2174.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>40.0</td>\n",
       "      <td>United-States</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>50.0</td>\n",
       "      <td>Self-emp-not-inc</td>\n",
       "      <td>83311.0</td>\n",
       "      <td>Bachelors</td>\n",
       "      <td>13.0</td>\n",
       "      <td>Married-civ-spouse</td>\n",
       "      <td>Exec-managerial</td>\n",
       "      <td>Husband</td>\n",
       "      <td>White</td>\n",
       "      <td>Male</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>13.0</td>\n",
       "      <td>United-States</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>38.0</td>\n",
       "      <td>Private</td>\n",
       "      <td>215646.0</td>\n",
       "      <td>HS-grad</td>\n",
       "      <td>9.0</td>\n",
       "      <td>Divorced</td>\n",
       "      <td>Handlers-cleaners</td>\n",
       "      <td>Not-in-family</td>\n",
       "      <td>White</td>\n",
       "      <td>Male</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>40.0</td>\n",
       "      <td>United-States</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>53.0</td>\n",
       "      <td>Private</td>\n",
       "      <td>234721.0</td>\n",
       "      <td>11th</td>\n",
       "      <td>7.0</td>\n",
       "      <td>Married-civ-spouse</td>\n",
       "      <td>Handlers-cleaners</td>\n",
       "      <td>Husband</td>\n",
       "      <td>Black</td>\n",
       "      <td>Male</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>40.0</td>\n",
       "      <td>United-States</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>28.0</td>\n",
       "      <td>Private</td>\n",
       "      <td>338409.0</td>\n",
       "      <td>Bachelors</td>\n",
       "      <td>13.0</td>\n",
       "      <td>Married-civ-spouse</td>\n",
       "      <td>Prof-specialty</td>\n",
       "      <td>Wife</td>\n",
       "      <td>Black</td>\n",
       "      <td>Female</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>40.0</td>\n",
       "      <td>Cuba</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    age         workclass    fnlwgt  education  education-num  \\\n",
       "0  39.0         State-gov   77516.0  Bachelors           13.0   \n",
       "1  50.0  Self-emp-not-inc   83311.0  Bachelors           13.0   \n",
       "2  38.0           Private  215646.0    HS-grad            9.0   \n",
       "3  53.0           Private  234721.0       11th            7.0   \n",
       "4  28.0           Private  338409.0  Bachelors           13.0   \n",
       "\n",
       "       marital-status         occupation   relationship   race     sex  \\\n",
       "0       Never-married       Adm-clerical  Not-in-family  White    Male   \n",
       "1  Married-civ-spouse    Exec-managerial        Husband  White    Male   \n",
       "2            Divorced  Handlers-cleaners  Not-in-family  White    Male   \n",
       "3  Married-civ-spouse  Handlers-cleaners        Husband  Black    Male   \n",
       "4  Married-civ-spouse     Prof-specialty           Wife  Black  Female   \n",
       "\n",
       "   capital-gain  capital-loss  hours-per-week native-country  \n",
       "0        2174.0           0.0            40.0  United-States  \n",
       "1           0.0           0.0            13.0  United-States  \n",
       "2           0.0           0.0            40.0  United-States  \n",
       "3           0.0           0.0            40.0  United-States  \n",
       "4           0.0           0.0            40.0           Cuba  "
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_train.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>age</th>\n",
       "      <th>workclass</th>\n",
       "      <th>fnlwgt</th>\n",
       "      <th>education</th>\n",
       "      <th>education-num</th>\n",
       "      <th>marital-status</th>\n",
       "      <th>occupation</th>\n",
       "      <th>relationship</th>\n",
       "      <th>race</th>\n",
       "      <th>sex</th>\n",
       "      <th>capital-gain</th>\n",
       "      <th>capital-loss</th>\n",
       "      <th>hours-per-week</th>\n",
       "      <th>native-country</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>25.0</td>\n",
       "      <td>Private</td>\n",
       "      <td>226802.0</td>\n",
       "      <td>11th</td>\n",
       "      <td>7.0</td>\n",
       "      <td>Never-married</td>\n",
       "      <td>Machine-op-inspct</td>\n",
       "      <td>Own-child</td>\n",
       "      <td>Black</td>\n",
       "      <td>Male</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>40.0</td>\n",
       "      <td>United-States</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>38.0</td>\n",
       "      <td>Private</td>\n",
       "      <td>89814.0</td>\n",
       "      <td>HS-grad</td>\n",
       "      <td>9.0</td>\n",
       "      <td>Married-civ-spouse</td>\n",
       "      <td>Farming-fishing</td>\n",
       "      <td>Husband</td>\n",
       "      <td>White</td>\n",
       "      <td>Male</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>50.0</td>\n",
       "      <td>United-States</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>28.0</td>\n",
       "      <td>Local-gov</td>\n",
       "      <td>336951.0</td>\n",
       "      <td>Assoc-acdm</td>\n",
       "      <td>12.0</td>\n",
       "      <td>Married-civ-spouse</td>\n",
       "      <td>Protective-serv</td>\n",
       "      <td>Husband</td>\n",
       "      <td>White</td>\n",
       "      <td>Male</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>40.0</td>\n",
       "      <td>United-States</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>44.0</td>\n",
       "      <td>Private</td>\n",
       "      <td>160323.0</td>\n",
       "      <td>Some-college</td>\n",
       "      <td>10.0</td>\n",
       "      <td>Married-civ-spouse</td>\n",
       "      <td>Machine-op-inspct</td>\n",
       "      <td>Husband</td>\n",
       "      <td>Black</td>\n",
       "      <td>Male</td>\n",
       "      <td>7688.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>40.0</td>\n",
       "      <td>United-States</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>18.0</td>\n",
       "      <td>nan</td>\n",
       "      <td>103497.0</td>\n",
       "      <td>Some-college</td>\n",
       "      <td>10.0</td>\n",
       "      <td>Never-married</td>\n",
       "      <td>nan</td>\n",
       "      <td>Own-child</td>\n",
       "      <td>White</td>\n",
       "      <td>Female</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>30.0</td>\n",
       "      <td>United-States</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    age  workclass    fnlwgt     education  education-num      marital-status  \\\n",
       "0  25.0    Private  226802.0          11th            7.0       Never-married   \n",
       "1  38.0    Private   89814.0       HS-grad            9.0  Married-civ-spouse   \n",
       "2  28.0  Local-gov  336951.0    Assoc-acdm           12.0  Married-civ-spouse   \n",
       "3  44.0    Private  160323.0  Some-college           10.0  Married-civ-spouse   \n",
       "4  18.0        nan  103497.0  Some-college           10.0       Never-married   \n",
       "\n",
       "          occupation relationship   race     sex  capital-gain  capital-loss  \\\n",
       "0  Machine-op-inspct    Own-child  Black    Male           0.0           0.0   \n",
       "1    Farming-fishing      Husband  White    Male           0.0           0.0   \n",
       "2    Protective-serv      Husband  White    Male           0.0           0.0   \n",
       "3  Machine-op-inspct      Husband  Black    Male        7688.0           0.0   \n",
       "4                nan    Own-child  White  Female           0.0           0.0   \n",
       "\n",
       "   hours-per-week native-country  \n",
       "0            40.0  United-States  \n",
       "1            50.0  United-States  \n",
       "2            40.0  United-States  \n",
       "3            40.0  United-States  \n",
       "4            30.0  United-States  "
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_test.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "train: 0.0    24720\n",
      "1.0     7841\n",
      "Name: income, dtype: int64\n",
      "test: 0.0    12435\n",
      "1.0     3846\n",
      "Name: income, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "print('train: {}\\ntest: {}'.format(y_train.value_counts(), y_test.value_counts()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ok, so our task here is to predict whether person makes over 50K per year. We'll use `CatBoostClassifier` to solve this problem. In CatBoost there are two possible objectives for binary classification: `Logloss` and `CrossEntropy`, we'll use the first one because second one works better with probabilities (while we have solid classes for each case).\n",
    "\n",
    "We are also going to use [Hyperopt](https://github.com/hyperopt/hyperopt) for hyper-parameter optimization because it support optimization on a single host and is one of the most common solutions for hyper-parameter optimization. Though there is a number of other hyper-parameter optimization frameworks like [Chocolate](https://github.com/AIworx-Labs/chocolate) and [Skopt](https://scikit-optimize.github.io)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "class UciAdultClassifierObjective(object):\n",
    "    def __init__(self, dataset, const_params, fold_count):\n",
    "        self._dataset = dataset\n",
    "        self._const_params = const_params.copy()\n",
    "        self._fold_count = fold_count\n",
    "        self._evaluated_count = 0\n",
    "        \n",
    "    def _to_catboost_params(self, hyper_params):\n",
    "        return {\n",
    "            'learning_rate': hyper_params['learning_rate'],\n",
    "            'depth': hyper_params['depth'],\n",
    "            'l2_leaf_reg': hyper_params['l2_leaf_reg']}\n",
    "    \n",
    "    # hyperopt optimizes an objective using `__call__` method (e.g. by doing \n",
    "    # `foo(hyper_params)`), so we provide one\n",
    "    def __call__(self, hyper_params):\n",
    "        # join hyper-parameters provided by hyperopt with hyper-parameters \n",
    "        # provided by the user\n",
    "        params = self._to_catboost_params(hyper_params)\n",
    "        params.update(self._const_params)\n",
    "        \n",
    "        print('evaluating params={}'.format(params), file=sys.stdout)\n",
    "        sys.stdout.flush()\n",
    "        \n",
    "        # we use cross-validation for objective evaluation, to avoid overfitting\n",
    "        scores = cb.cv(\n",
    "            pool=self._dataset,\n",
    "            params=params,\n",
    "            fold_count=self._fold_count,\n",
    "            partition_random_seed=20181224,\n",
    "            verbose=False)\n",
    "        \n",
    "        # scores returns a dictionary with mean and std (per-fold) of metric \n",
    "        # value for each cv iteration, we choose minimal value of objective \n",
    "        # mean (though it will be better to choose minimal value among all folds)\n",
    "        # because noise is additive\n",
    "        max_mean_auc = np.max(scores['test-AUC-mean'])\n",
    "        print('evaluated score={}'.format(max_mean_auc), file=sys.stdout)\n",
    "        \n",
    "        self._evaluated_count += 1\n",
    "        print('evaluated {} times'.format(self._evaluated_count), file=sys.stdout)\n",
    "        \n",
    "        # negate because hyperopt minimizes the objective\n",
    "        return {'loss': -max_mean_auc, 'status': hyperopt.STATUS_OK}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "def find_best_hyper_params(dataset, const_params, max_evals=100):    \n",
    "    # we are going to optimize these three parameters, though there are a lot more of them (see CatBoost docs)\n",
    "    parameter_space = {\n",
    "        'learning_rate': hyperopt.hp.uniform('learning_rate', 0.2, 1.0),\n",
    "        'depth': hyperopt.hp.randint('depth', 7),\n",
    "        'l2_leaf_reg': hyperopt.hp.uniform('l2_leaf_reg', 1, 10)}\n",
    "    objective = UciAdultClassifierObjective(dataset=dataset, const_params=const_params, fold_count=6)\n",
    "    trials = hyperopt.Trials()\n",
    "    best = hyperopt.fmin(\n",
    "        fn=objective,\n",
    "        space=parameter_space,\n",
    "        algo=hyperopt.rand.suggest,\n",
    "        max_evals=max_evals,\n",
    "        rstate=np.random.RandomState(seed=20181224))\n",
    "    return best\n",
    "\n",
    "def train_best_model(X, y, const_params, max_evals=100, use_default=False):\n",
    "    # convert pandas.DataFrame to catboost.Pool to avoid converting it on each \n",
    "    # iteration of hyper-parameters optimization\n",
    "    dataset = cb.Pool(X, y, cat_features=np.where(X.dtypes != np.float)[0])\n",
    "    \n",
    "    if use_default:\n",
    "        # pretrained optimal parameters\n",
    "        best = {\n",
    "            'learning_rate': 0.4234185321620083, \n",
    "            'depth': 5, \n",
    "            'l2_leaf_reg': 9.464266235679002}\n",
    "    else:\n",
    "        best = find_best_hyper_params(dataset, const_params, max_evals=max_evals)\n",
    "    \n",
    "    # merge subset of hyper-parameters provided by hyperopt with hyper-parameters \n",
    "    # provided by the user\n",
    "    hyper_params = best.copy()\n",
    "    hyper_params.update(const_params)\n",
    "    \n",
    "    # drop `use_best_model` because we are going to use entire dataset for \n",
    "    # training of the final model\n",
    "    hyper_params.pop('use_best_model', None)\n",
    "    \n",
    "    model = cb.CatBoostClassifier(**hyper_params)\n",
    "    model.fit(dataset, verbose=False)\n",
    "    \n",
    "    return model, hyper_params"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Warning: Custom metrics will not be evaluated because there are no test datasets\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "best params are {u'task_type': u'CPU', u'random_seed': 20181224, u'eval_metric': u'AUC', u'learning_rate': 0.4234185321620083, u'depth': 5, u'loss_function': u'Logloss', u'iterations': 100, u'l2_leaf_reg': 9.464266235679002, u'custom_metric': [u'AUC']}\n"
     ]
    }
   ],
   "source": [
    "# make it True if your want to use GPU for training\n",
    "have_gpu = False\n",
    "# skip hyper-parameter optimization and just use provided optimal parameters\n",
    "use_optimal_pretrained_params = True\n",
    "# number of iterations of hyper-parameter search\n",
    "hyperopt_iterations = 30\n",
    "\n",
    "const_params = dict({\n",
    "    'task_type': 'GPU' if have_gpu else 'CPU',\n",
    "    'loss_function': 'Logloss',\n",
    "    'eval_metric': 'AUC', \n",
    "    'custom_metric': ['AUC'],\n",
    "    'iterations': 100,\n",
    "    'random_seed': 20181224})\n",
    "\n",
    "model, params = train_best_model(\n",
    "    X_train, y_train, \n",
    "    const_params, \n",
    "    max_evals=hyperopt_iterations, \n",
    "    use_default=use_optimal_pretrained_params)\n",
    "print('best params are {}'.format(params), file=sys.stdout)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "def calculate_score_on_dataset_and_show_graph(X, y, model):\n",
    "    import sklearn.metrics\n",
    "    import matplotlib.pylab as pl\n",
    "    pl.style.use('ggplot')\n",
    "    \n",
    "    dataset = cb.Pool(X, y, cat_features=np.where(X.dtypes != np.float)[0])\n",
    "    fpr, tpr, _ = cbu.get_roc_curve(model, dataset, plot=True)\n",
    "    auc = sklearn.metrics.auc(fpr, tpr)\n",
    "    return auc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA8IAAAH/CAYAAACckGT3AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4zLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvIxREBQAAIABJREFUeJzs3Xl81NW9//H3mWTISggQEggJsm+yL4psogTcKBWlVWht1bbWPlxau9w+Wm6vYturuNTite29aitUREH4VcQialAElNUWUEHZhCQEEgKEkISsc35/DJkwZmHATL4zyev5eHDzPee7zCfk20venu/3HGOttQIAAAAAoJVwOV0AAAAAAADNiSAMAAAAAGhVCMIAAAAAgFaFIAwAAAAAaFUIwgAAAACAVoUgDAAAAABoVQjCAAAAAIBWhSAMAIAkY4zfn4iICHXo0EGTJk3SggULZK1t9PzMzEzdcsst6tatm6Kjo5WYmKjRo0dr7ty5OnnyZKPnejweLVu2TDfffLPS09MVHR2tuLg4DRgwQHfddZc++OCDC/5+PvvsM913330aNGiQ2rVrpzZt2ig1NVU33HCD/vrXv6q8vPyCrwkAQEth7Pn+ZQcAoBUwxkiSHnzwQUlSZWWl9u3bp3/84x+qrKzUPffco2eeeabOeeXl5fr+97+vRYsWKSYmRtddd5369u2r4uJivfvuu9q1a5eSkpK0fPlyTZw4sc75R48e1cyZM/XBBx+obdu2mjJlinr16iVrrfbu3as1a9aouLhY//M//6N77703oO/l4Ycf1ty5c+XxeHTFFVdo1KhRio+PV15entauXasDBw5o5MiR2rZt21f4GwMAIHwRhAEAUG0Q/vI/ix988IEmTpwoa63279+vHj16+O2/88479cILL2jEiBF67bXXlJ6e7ttnrdWf/vQn/fjHP1ZsbKy2bNmiAQMG+PaXlpZq7Nix2rFjh2699Vb9+c9/Vvv27f2uX1RUpCeeeEJRUVGaM2fOeb+P//7v/9acOXOUnp6uV199VZdffnmdY9544w09+eSTeu+9987/FwMAQAvEo9EAADRi3Lhx6t+/v6y1+uijj/z2bdiwQS+88ILat2+vN954wy8ES95wfe+99+oXv/iFiouLdf/99/vtf+qpp7Rjxw6NGzdOL730Up0QLEkJCQl6+OGH9fOf//y8tR48eFAPPfSQ3G63Vq1aVW8IlqRp06Zp9erVvvbatWtljNFDDz1U7/Hdu3dX9+7d/foWLFggY4wWLFig1atXa9KkSWrXrp2MMTp8+LAiIiI0fPjwBmu97rrrZIzRJ5984te/efNmzZw5U507d1abNm2Unp6uH/7wh8rNzT3v9w8AQKAIwgAABMjtdvu1n3vuOUnSD37wA3Xp0qXB8375y18qKipKmZmZ+uKLL3z9zz77rCTpN7/5jVyuxv9JjoqKOm99L7zwgiorK3XzzTdr0KBBX/l6gVi2bJmmTZumtm3b6u6779Ytt9yirl27KiMjQ9u3b9fHH39c55wjR47onXfe0ciRI/3q/Nvf/qZx48bpzTff1FVXXaWf/OQnGjVqlJ5//nmNGjVKWVlZTVIzAACRThcAAEAoW7dunT777DO1adNGl112md++DRs2SJIyMjIavUb79u01cuRIffjhh/rggw/Uo0cPZWdnKysrS5GRkbryyiubpNaaeiZPntwk1wvEqlWrtGrVKl177bV+/bfffrvefvttLVy4UE888YTfvkWLFqm6ulrf/e53fX179uzR3Xffre7du+v9999X165dffvWrFmjqVOn6sc//rH+8Y9/BPcbAgC0CgRhAADOUfN48LmTZVlr9cQTT9QZ9T1y5Igk1Xkkuj41x9Q84ltzbseOHRUdHd0ktddcMy0trUmuF4ivf/3rdUKwJN14441q166dXnrpJc2bN08RERG+fQsXLpTb7dasWbN8fX/5y19UWVmp+fPn+4VgyRvsp0+frpUrV+r06dNq27Zt8L4hAECrQBAGAOAcc+fO9WsbY/TXv/5Vd9xxh0MVhbYvj5LXiImJ0Te/+U0999xzeuutt3T99ddLkj766CN9+umnmjFjhpKSknzHb9y4UZL0/vvva+vWrXWul5+fr+rqau3Zs0cjR44MwncCAGhNCMIAAJyjZtbokpISbdy4Ud/73vd0991365JLLtHVV1/td2znzp31xRdfKDs7W/3792/0utnZ2ZKk1NRUSfKNLh8/flxlZWVNMircpUsX7d69W4cPH/7K1wpU586dG9x3++2367nnntPChQt9QXjhwoWS5PdYtOT9e5Ckxx9/vNHPKy4u/irlAgAgicmyAACoV1xcnDIyMrRy5Urf+6ylpaV+x4wfP16SlJmZ2ei1Tp486Ztxety4cZK8j0p369ZNVVVVWrduXZPUXFPPmjVrLui8mom6qqqq6t1fWFjY4Lk1y07VZ+zYserTp49ef/11FRYWqrKyUi+//LKSkpJ8wbhGu3btJEmnTp2StbbBP031PjUAoHUjCAMA0IghQ4boBz/4gXJycvTUU0/57fv+978vSXr++eeVl5fX4DWeeOIJlZeXKyMjw28d4rvuukuS9Lvf/U4ej6fROsrLy89b6x133CG3263ly5dr165dAV+vZtmmmlHrc+3bt0+nTp0672c35Lvf/a7Kysq0ZMkS/fOf/1RBQYFmz55dZwbuMWPGSJLWr19/0Z8FAECgCMIAAJzHf/7nfyoqKkpPPPGETp486eufOHGibrvtNp04cULTpk1TTk5OnXP/93//V/PmzVN8fLzmz5/vt++BBx7Q0KFDtX79en3nO9+pd+S1uLhYc+fOrTPzcn26d++uhx56SBUVFbrhhhu0bdu2eo9bvXq1rrvuOl+7f//+SkhI0IoVK5Sfn+/rP3PmTJ21jy/Ud77zHblcLv3973/X3//+d0neR6a/7N5775Xb7dYDDzygPXv21NlfUVFBSAYANBneEQYA4Dy6du2qu+++W/Pnz9djjz2mRx55xLfv2WefVVVVlV5++WX169dP1113nfr06aOSkhK99957+uSTT9SxY0ctX75cAwcO9LtubGysVq9erZkzZ+qll17SypUrNWXKFPXq1UvWWu3bt09r1qxRUVGRnnnmmYBq/fWvf62qqirNnTtXo0eP1tixYzVq1CjFx8crLy9P69at0969ezVq1CjfOW63Wz/+8Y/129/+VsOHD9eMGTNUVVWld955R6mpqb73mi9Genq6rrrqKq1Zs0aRkZEaPHiwhg8fXue4/v37629/+5vuvPNOXXrppbr22mvVt29fVVZWKisrS+vXr1enTp302WefXXQtAADUMLZmVhAAAFqxmnddG/pnMS8vTz179pQkHThwQCkpKX773377bT333HPauHGjjh07pujoaPXu3Vtf+9rXdP/996tDhw4NfrbH49Hy5cv18ssva8uWLSooKJDL5VK3bt00fvx43XnnnRo7duwFfT+7d+/Wn//8Z7333nvKyspSWVmZOnbsqGHDhmnmzJn69re/raioKN/x1lrNmzdPzz33nLKzs9W5c2fdeuuteuihh3wB/uDB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RFlr9de//lXTp09XcnKy3zFut1tpaWnq3bt30AtF6LOlxbKZr/vaZswkGWMcrAgAAAAA6mowCPfs2VM9e/aUJBljdPnllyshIaHZCkN4sScKZDe8XdsR11amU2fnCgIAAACABgQ0WdaUKVOCXQfCmN21XXbfLl/bDBgm02eggxUBAAAAQMMCnjU6NzdXa9euVW5uriorK+vs/9WvftWkhSE82L27/EPwxGtlEjs4WBEAAAAANC6gIHzgwAH913/9l9q1a6eCggKlpqaquLhYRUVFat++vZKSkoJdJ0KQtVZ293Zf21z3DRm328GKAAAAAOD8AloA+KWXXtKIESP09NNPS5Luu+8+Pffcc/rlL38pa62+9a1vBbVIhCa7aa1v20y8lhAMAAAAICwEFIQPHTqkSZNqZwD2eDySpBEjRmjGjBlatGhR8CpESLInCqRjR7yNiEgehwYAAAAQNgIKwpWVlYqOjpbL5VJ8fLxOnTrl25eWlqasrKygFYjQYwuP+80QbaayjjQAAACA8BFQEE5JSdHJkycleYPv2rVrffvWrVvHskqtiN27S3bdW762GXMVj0QDAAAACCsBTZY1bNgw7dy5U+PGjdOMGTM0b9483XHHHYqIiNDp06d12223BbtOhIA6k2ONy5DpmOxgRQAAAABw4QIKwrNnz/ZtDxs2THPnztWmTZtUUVGhYcOGadSoUUErEKHBWiu78mVf21w1TaYtTwIAAAAACD8BryN8rr59+6pv375NXQtCmP3n0tpGx2RCMAAAAICwdVFB+Fw5OTlatmyZfvKTnwR0fEFBgRYuXKidO3dKkgYPHqzbb7894LWIc3JytHTpUn366acqKytTUlKSrrnmGl1//fUX/T2gcbbktOSp9rXN2MkOVgMAAAAAX02jQdhaq6ysLBUUFCglJUVpaWm+fVlZWVq2bJm2bNmiNm3aBPRh5eXlevjhh+V2u3XPPffIGKNXXnlFc+fO1eOPP67o6OhGz9+/f78efvhhDRw4UD/84Q8VGxuro0ePqqysLKDPx0U6ku3bNF+b5VtGCwAAAADCUYNBuLCwUE888YT27t3r65swYYJ+9KMfacGCBXrnnXcUERGhqVOn6qabbgrow9asWaO8vDzNnz9fnTt3liRdcskluv/++5WZmalp06Y1eK7H49EzzzyjQYMG6Re/+IWvf9CgQQF9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ERHusY8++khHjhxpEoQHDBigRYsWKTY2tt1ev7XuvvtuXXfddaqtrdXRo0e1du1aFRYWatGiRQoICLis5/rvf/+rtWvX6tZbbyUIAwBaRBAGAHRI8fHxio6O9nUZV2TQoEHu68nJyZo5c6Y2btzYrkH426/Tkq5du7b6se0tOjra/dpJSUmqqanRW2+9pfz8fPXv398nNQEA/B9BGADgdxwOh1atWqUDBw6opKREXbp0Uf/+/fXDH/5Qffr0aXHbDz/8UBs2bNDp06fVqVMnRUZG6o477tCYMWPcjzl48KDefvttHT9+XJI0ePBgTZs27Yr2SAcGBio+Pl4HDhxwj1VWVmr16tX6+OOPVV5erqioKN1222268847Gz1mzZo1ysvLU1lZmUJCQhQXF6eHHnpIffr0aTI1+vnnn9f27dslSZMmTZIkXXXVVfrzn//cZGr0K6+8ok8++UQvvviiOnX6ejkRh8OhH//4xxozZoymTZsmSSorK1N2drY++eQTnT9/XtHR0fr+97+v0aNHX/b3QpKuvvpqSVJpaWmjIJyVlaVPP/1URUVFCgwMVL9+/XT//fdrwIABkr6e5i5JmZmZ7u0apr3X1dVp/fr12rp1q0pKShQWFqabb75ZGRkZslqtV1QrAKDjIggDADokp9Opuro6922LxeIObQ6HQw6HQ/fcc4+6d++u8vJybd68WU8++aSee+45devW7aLPeejQIb3wwgu68847NW3aNDmdTtlsNtntdvdj9uzZo2effVbXX3+9fv7zn8vpdGr9+vX69a9/rWefffaKjm0tLi5W165d3e/rt7/9rb744gtNnjxZsbGxysvL04oVK1ReXq7JkydLklasWKG9e/cqIyND0dHRqqio0OHDh1VZWXnR15g0aZLKy8v1xRdfaPbs2ZKkzp07X/SxaWlpysnJ0YEDB5SSkuIez8vL04ULF5SWliZJstvt+r//+z/V1dVp0qRJioyM1GeffaaXX35ZtbW1+t73vnfZ34uSkhJJ9SH9m86ePavx48erV69eqqqq0tatW/XrX/9azzzzjGJiYnT99derqKhI7777rmbPnq3u3btLkvtnvXTpUn322WeaMGGCBg4cKJvNpuzsbJWWlmrWrFmXXScAoGMjCAMAOqSZM2c2up2YmKinnnpKkhQaGqqf/OQn7vucTqdSUlL08MMPa+fOnbrjjjsu+pzHjh1TWFiYHnjgAffYN4Ogy+XSihUrlJyc7A6TknTttdcqMzNT7733nntPaUsaAnx5ebk2bdqk/Px8jR8/XlJ92Dx69KgyMzPdgTMlJUVVVVX629/+pnHjxik0NFRHjx5VWlpaoz2vN9xwQ7OvGR0drbCwMFmt1ktOg05MTFRUVJQ+/PDDRu//ww8/VFxcnOLj4yVJf//733XmzBn94Q9/cE9TT05Olt1u11tvvaX09PRGe5QvpuEDjZqaGh07dkzvvvuuRo4c6X6NBo8++mijbVJSUjRr1ixt2bJF06ZNU3h4uDs8x8fHKyoqyv34gwcPavfu3ZoxY4Zuvvlmd51du3bV8uXLNXHiRMXFxbVYJwDAvxCEAQAd0uzZsxut9NylS5dG9+/YsUPvvfeeCgsLdeHCBfd4YWFhs8/Zv39/nT9/XsuWLdPIkSN1zTXXuPfUStLJkydVUlKiSZMmNdobHRwcrIEDB+rw4cOtqv2+++5zX7darRo/frx77PDhwwoICGiyivSoUaO0detWHTt2TMOHD1f//v21ZcsWhYaGKjk5WfHx8ZcMna1lsViUlpamDRs2qKqqSsHBwSorK9O+ffsa1b53714lJiYqMjKy0fcjJSVFH3zwgQoLCy85Xfyll17SSy+95L7dv39/PfbYY00et2/fPr3zzjv68ssvVVFR4R5v6ef5zTqtVqtuuOGGJnVK9d9zgjAAmAtBGADQIcXFxTW7WNbHH3+spUuX6tZbb9W9996r8PBwWSwWLV68WDU1Nc0+59ChQzVz5kxt3rxZS5YskVS/t3fatGmKi4vT+fPnJUkvvPCCXnjhhSbbf3s6b3N+97vfSao/fVJERIQCA7/+77iiokJhYWFNVkxumOrbEAIffvhhrVu3Trm5uVq9erXCwsJ0yy23KCMjo9kpz5dj1KhRWrt2rT7++GOlpaVpx44dcjqd7j2qUv3xwcePH28Ujr+pvLz8kq9zzz33aMSIEaqurtbOnTv1z3/+U2+88UajPfrHjx/X008/reHDh+uRRx5R9+7d1alTJy1fvrzFn2eD8+fPq6amRlOnTr3iOgEA/oUgDADwOzt27FDfvn0bTad1OByNjvVtzsiRIzVy5EhVVVXp4MGDWrVqlX73u99p+fLlCg0NlSRNnTpV1157bZNtW7voUkurIYeGhqq8vFx1dXWNwvC5c+fc90v1e8CnTJmiKVOmqLi4WLt379bq1atltVqbDaaXo3fv3ho4cKC2bdumtLQ0bdu2TUOHDm10DHRYWJgiIiKanQ5+qYXJJCkqKsr9/UhKSlJlZaW2bNmisWPHKiEhQZK0e/duWa1W/eIXv2j0PamoqHB/QNCS0NBQBQUFacGCBRe9v0ePHpd8DgCAf2mfOVQAABhIdXV1k2nCH374oVwuV6ufIzg4WKmpqRozZozOnDkju92umJgY9erVSzabTf3792/y1R7Ta5OSklRXV6ePPvqo0fj27dtltVo1cODAJttERUXprrvuUkxMjAoKCpp9bqvVKofD0epabrnlFh04cEAHDx7UiRMn3McsNxg2bJhsNpsiIyMv+v349nT11pg6daoCAwO1du1a95jD4VBAQIAsFot7bN++ffrf//7X5P01PP7bdVZXV6u6uvqidV7JAmcAgI6NPcIAAL8zbNgwvfHGG/rLX/6i4cOH68SJE9q0adMlg9maNWtUXl6uIUOGqHv37iotLdWmTZvUv39/957Yhx56SM8++6wcDoe+853vKCwsTOfOndORI0d01VVXNTrF0ZUYMWKEEQpzHQAAAoFJREFUBg0apJdfflnnzp1T37599cknn+iDDz7QxIkT3XXMmzdPN9xwg+Li4hQUFKRDhw6poKBA6enpzT53TEyM/vWvfyknJ0fx8fHq3Llzi+F95MiRWrFihZYtW6agoKAmi3F9//vf165duzR//nyNGzdOvXv31oULF1RYWKgjR45ozpw5l/3+e/bsqbFjx+of//iH8vPzFR8fr2HDhmnTpk1avny5brnlFp08eVLr1q1rsie34XjkTZs2KS0tTQEBAerXr5+Sk5N14403asmSJRo/frz7lEslJSX69NNPNW3atA57TmoAwJUhCAMA/M73vvc9nT17Vlu3btU///lPDRw4UHPnztXTTz/d4nYDBw7Upk2btGLFClVUVKhbt25KSUlRRkaG+zGpqalasGCB3nnnHb300ktyOBzq3r27Bg4c2GSBqyvRqVMnzZs3T6tXr9a7777rPo/w9OnTG4Xsa665Rjt37tQ777wjp9Opq666Sg8++KBuv/32Zp87PT1dx48f16pVq2S3293nEW5OaGiohg8frj179igtLU3BwcGN7g8JCdHixYv11ltv6Z133tHZs2cVEhKivn376sYbb7zi78EPfvAD5ebmau3atZo9e7auu+46PfDAA9q4caN27dqluLg4zZgxQ9nZ2Y22S0hI0MSJE7Vlyxa9//77crlc7vMIz5w5Uxs3btQHH3ygdevWyWq1KjIyUikpKQoPD7/iWgEAHZPFdTnzxAAAAAAA6OA4RhgAAAAAYCoEYQAAAACAqRCEAQAAAACmQhAGAAAAAJgKQRgAAAAAYCoEYQAAAACAqRCEAQAAAACmQhAGAAAAAJgKQRgAAAAAYCr/DyK+Rcw4MEpHAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 1152x576 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "0.9222174548421422"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "calculate_score_on_dataset_and_show_graph(X_test, y_test, model)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
